/*******************************************************************************
 * Copyright (c) 2010 L.Carbonnaux.
 *******************************************************************************/

package org.lcx.taskvision.ui;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.osgi.util.NLS;
import org.lcx.taskvision.core.ITaskVisionConstants;
import org.lcx.taskvision.core.TaskVisionClient;
import org.lcx.taskvision.core.TaskVisionCorePlugin;
import org.lcx.taskvision.core.model.TaskVisionSpreadSheet;
import org.lcx.taskvision.core.model.TaskVisionWorkSheet;

/**
 * @author Laurent Carbonnaux
 */
public class TaskVisionUiTools {


	// The shared instance
	private static TaskVisionUiTools instance;

	/**
	 * The constructor
	 */
	public TaskVisionUiTools() {
	}


	/**
	 * Returns the shared instance
	 *
	 * @return the shared instance
	 */
	public static TaskVisionUiTools getDefault() {
		if(instance==null){
			instance = new TaskVisionUiTools();
		}
		return instance;
	}


	/**
	 * Update query options from repository
	 */
	public static void updateTagQueryOptions(TaskRepository repository, IProgressMonitor monitor) {
		if (monitor.isCanceled())
			throw new OperationCanceledException();
		TaskVisionClient client = null;
		try {
			client = TaskVisionCorePlugin.getClientManager().getClient(repository);
	
			// get the preferences store so that we can change the data in it
			IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
			final Map<String, Set<String>> tagList = new HashMap<String, Set<String>>();
			client.getListTags(tagList);
			TaskVisionUiTools.getTagList(repository.getRepositoryUrl(), tagList, prefs);
	
		} catch (Exception e) {
			StatusHandler.fail(new Status(IStatus.ERROR, TaskVisionCorePlugin.PLUGIN_ID,
				NLS.bind(Messages.ScrumVisionUiTools_repository_configuration_Error, repository.getRepositoryLabel()), e));
			
			return;
		}
	}


	/**
	 * Update spreadsheet and worksheet list from global repository
	 */
	public static void updateSpreadSheetList(TaskRepository repository, IProgressMonitor monitor) {
		
		URL repositoryUrl; 
		try {
			repositoryUrl = new URL(repository.getUrl());
		} catch (Exception e) {
			StatusHandler.fail(new Status(IStatus.ERROR, TaskVisionCorePlugin.PLUGIN_ID,
					NLS.bind(Messages.ScrumVisionUiTools_repository_not_valid_Error, repository.getUrl()), e));
			
			return;
		}

		if (monitor.isCanceled())
			throw new OperationCanceledException();
		TaskVisionClient client = null;
		try {
			client = TaskVisionCorePlugin.getClientManager().getClient(repository);
	
			// get the preferences store so that we can change the data in it
			final List<TaskVisionSpreadSheet> list = new ArrayList<TaskVisionSpreadSheet>();
			client.getListSpreadSheets(repositoryUrl, list);
			TaskVisionUiTools.setSpreadSheetListToPrefs(repositoryUrl, list);
	
		} catch (Exception e) {
			StatusHandler.fail(new Status(IStatus.ERROR, TaskVisionCorePlugin.PLUGIN_ID,
					NLS.bind(Messages.ScrumVisionUiTools_repository_configuration_Error, repository.getRepositoryLabel()), e));
			
			return;
		}
	
	
		monitor.worked(1);
	}

	/**
	 * Strore spreadhseet lists to prefs for a google account
	 */
	public static void setSpreadSheetListToPrefs(URL repositoryUrl, List<TaskVisionSpreadSheet> list) throws IOException {
		
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();

		List<String> listName = new ArrayList<String>();
		Map<String, List<String>> listWorkWheetNames = new HashMap<String, List<String>>(); 

		// for all spreadsheets
		for (TaskVisionSpreadSheet spreadsheet : list) {
			listName.add(spreadsheet.getName());
			setPrefForSpreadsheet(repositoryUrl.toString(), spreadsheet, listWorkWheetNames, prefs);
		}
	
		if (!list.isEmpty()) {
			setPrefForSettingsPage(repositoryUrl.toString(), listName, listWorkWheetNames, prefs);
		}
		
	}

	public static void setPrefForSpreadsheet(String repositoryUrl, TaskVisionSpreadSheet spreadsheet, 
			Map<String, List<String>> listWorkWheetNames, IPreferenceStore prefs) {
		List<String> listWorkSheetName = new ArrayList<String>();
		// set pref for spreadsheet id
		prefs.setValue(ITaskVisionConstants.PREF_SPREADSHEET_ID + ITaskVisionConstants.PREF_DELIM_REPOSITORY 
				+ repositoryUrl + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadsheet.getName(),
				spreadsheet.getWorksheetFeedUrl().toString());
		// for all worksheets of the spreadsheet
		for (TaskVisionWorkSheet worksheet : spreadsheet.getWorksheets()) {
			listWorkSheetName.add(worksheet.getName());

			prefs.setValue(ITaskVisionConstants.PREF_WORKSHEET_ID + ITaskVisionConstants.PREF_DELIM_REPOSITORY 
					+ repositoryUrl + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadsheet.getName()
					+ ITaskVisionConstants.PREF_DELIM_WORKSHEET + worksheet.getName() ,
					worksheet.getId());

			prefs.setValue(ITaskVisionConstants.PREF_WORKSHEET_WSURL + ITaskVisionConstants.PREF_DELIM_REPOSITORY 
					+ repositoryUrl + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadsheet.getName()
					+ ITaskVisionConstants.PREF_DELIM_WORKSHEET + worksheet.getName() ,
					worksheet.getListFeedUrl().toString());

			prefs.setValue(ITaskVisionConstants.PREF_WORKSHEET_CFURL + ITaskVisionConstants.PREF_DELIM_REPOSITORY 
					+ repositoryUrl + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadsheet.getName()
					+ ITaskVisionConstants.PREF_DELIM_WORKSHEET + worksheet.getName() ,
					worksheet.getCellFeedUrl().toString());
			
		}
		listWorkWheetNames.put(spreadsheet.getName(), listWorkSheetName);
	}
	
	public static void setPrefForSettingsPage(String repositoryUrl,
			List<String> listName, Map<String, List<String>> listWorkWheetNames, IPreferenceStore prefs) {
		
		prefs.setValue(ITaskVisionConstants.PREF_SPREADSHEET_NAME + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl,
				TaskVisionUiTools.queryOptionsToString(listName));
		
		for (Iterator<String> iterator = listWorkWheetNames.keySet().iterator(); iterator.hasNext();) {
			String spreadSheet = (String) iterator.next();
			List<String> listWorkSheetName = listWorkWheetNames.get(spreadSheet);
			prefs.setValue(ITaskVisionConstants.PREF_WORKSHEET_NAME + ITaskVisionConstants.PREF_DELIM_REPOSITORY 
					+ repositoryUrl + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadSheet,
					TaskVisionUiTools.queryOptionsToString(listWorkSheetName));
		}
	}
	
	/**
	 * get the tags of the repository
	 */
	public static void getTagList(String url, Map<String, Set<String>> tagList, IPreferenceStore prefs) throws IOException {
	
		if(tagList!=null){
			for(String key : tagList.keySet()) {
				Set<String> set = tagList.get(key);
				if(set!=null){
					prefs.setValue(key + ITaskVisionConstants.PREF_DELIM_REPOSITORY + url,
						TaskVisionUiTools.queryOptionsToString(set));
				}
			}
		}
		
	}


	/**
	 * Update query options from SpreadSheet repository
	 */
	public static void updateSpreadSheetOptions(URL repositoryUrl, TaskVisionClient client, IPreferenceStore prefs) throws IOException {
		final List<TaskVisionWorkSheet> list = new ArrayList<TaskVisionWorkSheet>();
		client.getListWorkSheets(repositoryUrl, list);
		
		List<String> listName = new ArrayList<String>();
		
		for (TaskVisionWorkSheet worksheet : list) {
			listName.add(worksheet.getName());
	
			prefs.setValue(ITaskVisionConstants.PREF_WORKSHEET_WSURL + ITaskVisionConstants.PREF_DELIM_REPOSITORY 
					+ repositoryUrl + ITaskVisionConstants.PREF_DELIM_WORKSHEET + worksheet.getName() ,
					worksheet.getListFeedUrl().toString());
	
		}
	
		if (!list.isEmpty()) {
			prefs.setValue(ITaskVisionConstants.PREF_SPREADSHEET_NAME + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl,
					TaskVisionUiTools.queryOptionsToString(listName));
		}
	}

	public static String getUploadedRepositoryUrl() {
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
		String pref = prefs.getString(ITaskVisionConstants.PREF_REPOSITORY_UPLOADED_URL); 
		return pref;
	}

	public static String[] getSpreadSheetOptions(String prefId, String repositoryUrl) {
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
		String pref = prefs.getString(prefId + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl);
		return TaskVisionUiTools.convertQueryOptionsToArray(pref);
	}

	public static String[] getWorkSheetOptions(String prefId, String repositoryUrl, String spreadSheetName) {
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
		String pref = prefs.getString(prefId + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadSheetName); 
		return TaskVisionUiTools.convertQueryOptionsToArray(pref);
	}

	public static String getListFeedURL(String repositoryUrl, String spreadSheet, String workSheet) {
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
		String key = ITaskVisionConstants.PREF_WORKSHEET_WSURL + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl;
		if(spreadSheet!=null){
			key = key + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadSheet;
		}
		key = key + ITaskVisionConstants.PREF_DELIM_WORKSHEET+ workSheet;
		
		String pref = prefs.getString(key); 
		return pref;
	}

	public static String getCellFeedURL(String repositoryUrl, String spreadSheet, String workSheet) {
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
		String key = ITaskVisionConstants.PREF_WORKSHEET_CFURL + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl;
		if(spreadSheet!=null){
			key = key + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadSheet;
		}
		key = key + ITaskVisionConstants.PREF_DELIM_WORKSHEET+ workSheet;
		
		String pref = prefs.getString(key); 
		return pref;
	}
	
	public static String getSpreadsheetId(String repositoryUrl, String spreadSheetName) {
		IPreferenceStore prefs = TaskVisionUiPlugin.getDefault().getPreferenceStore();
		String key = ITaskVisionConstants.PREF_SPREADSHEET_ID + ITaskVisionConstants.PREF_DELIM_REPOSITORY + repositoryUrl;
		key = key + ITaskVisionConstants.PREF_DELIM_SPREADSHEET + spreadSheetName;
		String pref = prefs.getString(key); 
		return pref;
	}

	static String queryOptionsToString(List<String> array) {
	
		StringBuffer buffer = new StringBuffer();
		for (String string : array) {
			buffer.append(string);
			buffer.append(ITaskVisionConstants.PREF_DELIM_SPREADSHEET);
		}
		return buffer.toString();
	}


	static String queryOptionsToString(Set<String> array) {
	
		StringBuffer buffer = new StringBuffer();
		for (String string : array) {
			buffer.append(string);
			buffer.append(ITaskVisionConstants.PREF_DELIM_SPREADSHEET);
		}
		return buffer.toString();
	}


	static String[] convertQueryOptionsToArray(String values) {
		// create a new string buffer and array list
		StringBuffer buffer = new StringBuffer();
		List<String> options = new ArrayList<String>();
	
		char[] chars = values.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if (chars[i] == ITaskVisionConstants.PREF_DELIM_SPREADSHEET) {
				options.add(buffer.toString());
				buffer = new StringBuffer();
			} else {
				buffer.append(chars[i]);
			}
		}
	
		// create a new string array with the same size as the array list
		String[] array = new String[options.size()];
	
		// put each element from the list into the array
		for (int j = 0; j < options.size(); j++)
			array[j] = options.get(j);
		return array;
	}
}
